#include "glwidget.h"
#include "gltexture.h"

GLWidget::GLWidget(QWidget *parent)
    :   QGLWidget(parent)
{
}

void GLWidget::createTexture()
{
    int pixWidth, pixHeight;
    GLenum format;
/* a real image
    QPixmap pixmap = QPixmap(QString(":images/smiley.png"));
    QImage glImg = QGLWidget::convertToGLFormat(pixmap.toImage());
    GLubyte *pixels = glImg.bits();
    pixWidth = glImg.width();
    pixHeight = glImg.height();
    format = GL_RGBA;
*/
///*
    // tutorial image pixels need to be mirrored vertically -- using QImage
    QImage img(2, 2, QImage::Format_RGB32);
    QRgb value;
    value = qRgb(255, 0, 0);    // red
    img.setPixel(0, 0, value);
    value = qRgb(0, 255, 0);    // green
    img.setPixel(1, 0, value);
    value = qRgb(0, 0, 255);    // blue
    img.setPixel(0, 1, value);
    value = qRgb(255, 255, 0);  // yellow
    img.setPixel(1, 1, value);
    QImage glImg = QGLWidget::convertToGLFormat(img);
    GLubyte *pixels = glImg.bits();
    pixWidth = 2;
    pixHeight = 2;
    format = GL_RGBA;
//*/
    _userObject.setTexture(QSharedPointer<GLTexture>(new GLTexture(pixels, pixWidth, pixHeight, GLTexture::FormatRGBA, GLTexture::Target2D)));
    _userObject.texture()->setMagnificationFilter(GLTexture::MagnificationNearest);
    _userObject.texture()->setMinificationFilter(GLTexture::MinificationNearest);
    //for a gradient effect, uncomment
/*
    _userObject.texture()->setMagnificationFilter(GLTexture::MagnificationLinear);
    _userObject.texture()->setMinificationFilter(GLTexture::MinificationLinear);
*/
    _userObject.texture()->setSCoordinateWrap(GLTexture::WrapClampToEdge);
    _userObject.texture()->setTCoordinateWrap(GLTexture::WrapClampToEdge);
}

void GLWidget::resizeGL(int width, int height)
{
    (void)width;
    (void)height;
}


void GLWidget::initializeGL()
{

    const char vShaderSrc[] =
            "attribute vec4 a_position;   \n"
            "attribute vec2 a_texCoord;   \n"
            "varying vec2 v_texCoord;     \n"
            "void main()                  \n"
            "{                            \n"
            "   gl_Position = a_position; \n"
            "   v_texCoord = a_texCoord;  \n"
            "}                            \n";
    const char fShaderSrc[] =
            "mediump float;                            \n"
            "varying vec2 v_texCoord;                            \n"
            "uniform sampler2D s_texture;                        \n"
            "void main()                                         \n"
            "{                                                   \n"
            "  gl_FragColor = texture2D( s_texture, v_texCoord );\n"
            "}                                                   \n";

    // Load the shaders and get a linked program object
    _userObject.loadProgram(vShaderSrc, fShaderSrc);

    // Get the attribute locations
    _userObject.setPositionLocation(_userObject.programObject()->attributeLocation("a_position"));
    _userObject.setTexCoordLocation(_userObject.programObject()->attributeLocation("a_texCoord"));

    // Get the sampler location
    _userObject.setSamplerLocation(_userObject.programObject()->uniformLocation("s_texture"));

    // Load the texture
    createTexture();
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);

}

void GLWidget::paintGL()
{
    static const GLfloat vertexCoords[] = {
        -0.5f,  -0.5f, 0.0f,  // Position 0
        0.0f,  0.0f,        // TexCoord 0
        -0.5f, 0.5f, 0.0f,  // Position 1
        0.0f,  1.0f,        // TexCoord 1
        0.5f, 0.5f, 0.0f,  // Position 2
        1.0f,  1.0f,        // TexCoord 2
        0.5f,  -0.5f, 0.0f,  // Position 3
        1.0f,  0.0f         // TexCoord 3
    };
//    GLushort indices[] = { 0, 1, 2, 0, 2, 3 }; // no culling so it displays
    GLushort indices[] = { 0, 3, 2, 0, 2, 1 };
    glViewport(0, 0, width(), height());
    glClear(GL_COLOR_BUFFER_BIT);
    _userObject.programObject()->bind();
    _userObject.programObject()->setAttributeArray(_userObject.positionLocation(), GL_FLOAT, vertexCoords, 3, 5 * sizeof(GL_FLOAT));
    _userObject.programObject()->setAttributeArray(_userObject.texCoordLocation(), GL_FLOAT, &vertexCoords[3], 2, 5 * sizeof(GL_FLOAT));
    _userObject.programObject()->enableAttributeArray(_userObject.positionLocation());
    _userObject.programObject()->enableAttributeArray(_userObject.texCoordLocation());
    _userObject.texture()->activate(0);
    _userObject.texture()->bind();
    _userObject.programObject()->setUniformValue(_userObject.samplerLocation(), 0);
    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices);

}

